using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class MazeGenerator : MonoBehaviour
{
    [SerializeField]
    private MazeCell _mazeCellPrefab; // 迷宫单元格预制体

    [SerializeField]
    private int _mazeWidth; // 迷宫宽度（x轴方向单元格数量）

    [SerializeField]
    private int _mazeDepth; // 迷宫深度（z轴方向单元格数量）

    [SerializeField]
    private int _seed; // 随机种子

    [SerializeField]
    private bool _useSeed; // 是否使用指定种子

    private MazeCell[,] _mazeGrid; // 迷宫网格二维数组

    void Start()
    {
        GenerateCell();
        
        GenerateMaze(null, _mazeGrid[0, 0]);
    }

    // 生成迷宫单元格网格
    private void GenerateCell()
    {
        // 初始化随机种子
        if (_useSeed)
        {
            Random.InitState(_seed); // 使用指定的种子
        }
        else
        {
            int randomSeed = Random.Range(1, 1000000); // 生成随机种子
            Random.InitState(randomSeed);
            Debug.Log(randomSeed); // 输出种子以便重现
        }

        // 初始化迷宫网格
        _mazeGrid = new MazeCell[_mazeWidth, _mazeDepth];

        // 生成迷宫单元格
        for (int x = 0; x < _mazeWidth; x++)
        {
            for (int z = 0; z < _mazeDepth; z++)
            {
                _mazeGrid[x, z] = Instantiate(_mazeCellPrefab, new Vector3(x, 0, z), Quaternion.identity, transform);
                _mazeGrid[x, z].transform.localPosition = new Vector3(x, 0, z);
            }
        }
    }

    // 使用DFS深度优先算法生成迷宫路径
    private void GenerateMaze(MazeCell previousCell, MazeCell currentCell)
    {
        currentCell.Visit(); // 标记当前单元格为已访问
        ClearWalls(previousCell, currentCell); // 清除相邻单元格之间的墙
        MazeCell nextCell;

        do
        {
            nextCell = GetNextUnvisitedCell(currentCell); // 获取下一个未访问的相邻单元格

            if (nextCell != null)
            {
                GenerateMaze(currentCell, nextCell); // 递归生成迷宫
            }
        } while (nextCell != null); // 直到没有未访问的相邻单元格为止
    }

    // 获取下一个未访问的相邻单元格
    private MazeCell GetNextUnvisitedCell(MazeCell currentCell)
    {
        var unvisitedCells = GetUnvisitedCells(currentCell).ToList();

        //随机获取下一个相邻单元格
        return unvisitedCells.Count > 0 ? unvisitedCells[Random.Range(0, unvisitedCells.Count)] : null;
    }

    // 获取所有未访问的相邻单元格
    private IEnumerable<MazeCell> GetUnvisitedCells(MazeCell currentCell)
    {
        int x = (int)currentCell.transform.localPosition.x;
        int z = (int)currentCell.transform.localPosition.z;

        // 检查右侧单元格
        if (x + 1 < _mazeWidth)
        {
            var cellToRight = _mazeGrid[x + 1, z];

            if (cellToRight.IsVisited == false)
            {
                yield return cellToRight;
            }
        }

        // 检查左侧单元格
        if (x - 1 >= 0)
        {
            var cellToLeft = _mazeGrid[x - 1, z];

            if (cellToLeft.IsVisited == false)
            {
                yield return cellToLeft;
            }
        }

        // 检查前方单元格
        if (z + 1 < _mazeDepth)
        {
            var cellToFront = _mazeGrid[x, z + 1];

            if (cellToFront.IsVisited == false)
            {
                yield return cellToFront;
            }
        }

        // 检查后方单元格
        if (z - 1 >= 0)
        {
            var cellToBack = _mazeGrid[x, z - 1];

            if (cellToBack.IsVisited == false)
            {
                yield return cellToBack;
            }
        }
    }

    // 清除两个相邻单元格之间的墙
    private void ClearWalls(MazeCell previousCell, MazeCell currentCell)
    {
        if (previousCell == null) return;// 起始单元格没有前一个单元格

        Vector3 dir = currentCell.transform.localPosition - previousCell.transform.localPosition;

        if (dir.x > 0)
        { // 当前在previous的右侧
            previousCell.ClearRightWall();
            currentCell.ClearLeftWall();
        }
        else if (dir.x < 0)
        { // 左侧
            previousCell.ClearLeftWall();
            currentCell.ClearRightWall();
        }
        else if (dir.z > 0)
        { // 前方
            previousCell.ClearFrontWall();
            currentCell.ClearBackWall();
        }
        else if (dir.z < 0)
        { // 后方
            previousCell.ClearBackWall();
            currentCell.ClearFrontWall();
        }
    }
}